home *** CD-ROM | disk | FTP | other *** search
- INTRODUCCION AL ASM: LA INSTRUCCION MOV (I)
- ===========================================
-
- La operación más básica que el uP es capaz de realizar es el movimiento de
- datos (números) de un lugar a otro. Puede moverlos de un registro a otro, de
- un registro a la memoria o de la memoria a un registro.
-
- La instrucción en lenguaje ensamblador que representa esta operación se
- denomina 'MOV', del inglés 'move', y puede traducirse en muchos códigos de
- operación distintos en función del origen y el destino del dato. La instrucción
- MOV tiene dos operandos, que van después del 'mov' dejando uno o varios separa-
- dores entre el 'MOV' y el primer operando (diciendo separadores nos referire-
- mos siempre a los espacios - carácter 32d o 20h - y a los tabuladores - carác-
- ter 09) y separados por una coma y/o varios separadores. La sintáxis es la
- siguiente:
-
- MOV destino,origen
-
- En esta instrucción 'origen' significa el lugar de donde el uP recoge el
- dato a mover y 'destino' el lugar donde lo escribe después. Estos operandos
- pueden ser de muchas formas, y en función de la forma de estos se habla del
- 'modo de direccionamiento', que es el modo en como se accede al destino o al
- origen. Podríamos dar una larga y tediosa lista de los nombres de todos los
- modos de direccionamiento, pero lo que haremos será ir viendo ejemplos fácil-
- mente asimilables, de forma que luego quien quiera pueda aprenderse los nombres
- de los distintos modos de direccionamiento.
-
- Uno de los usos más sencillos es el de mover un dato de un registro a otro.
- Por ejemplo, para mover el dato del registro BX al registro AX escribiríamos:
-
- MOV AX,BX
-
- El contenido anterior del registro AX se pierde, de manera que el valor del
- BX 'pisa' lo que hubiera en el AX. Después de ejecutarse esta instrucción, los
- registros BX y AX contendrán el mismo valor, el contenido anterior del BX.
-
- De la misma forma, podemos comprender las siguientes instrucciones:
-
- MOV AX,DS
- MOV ES,AX
- MOV DX,AX
- ...
-
- Hacemos aquí un pequeño inciso para explicar cómo se añaden los comentarios
- a los listados en ASM: cuando el ensamblador encuentra un punto y coma (carác-
- ter ';'), ignora todos los caracteres hasta que encuentra el final de la línea
- actual. Por tanto, las instrucciones anteriores se pueden comentar:
-
- MOV AX,DS ; Carga AX con el valor del DS
- MOV ES,AX ; ES = AX
- MOV DX,BX ; DX <- BX
-
- Esta convención para los comentarios la aceptan los ensambladores como el
- MASM o el TASM, pero también lo acepta el DEBUG del MS-DOS (más adelante
- veremos cómo usarlo).
-
- Retomemos los usos de la instrucción MOV. Otra de las posibilidades es
- cargar en un registro directamente un valor. Por ejemplo, podemos inicializar
- los registros AX, BX, CX y DX a 1,2,3 y 4 respectivamente con las siguientes
- instrucciones:
-
- MOV AX,1
- MOV BX,2
- MOV CX,3
- MOV DX,4
-
- Un punto que me gustaría destacar respecto al uso 'MOV reg,valor' es que
- los registros de segmento no se pueden cargar directamente. Es decir, no
- existe código de operación para la instrucción
-
- MOV DS,0040h
-
- Sino que hay que hacerlo necesariamente por medio de otro registro:
-
- MOV AX,0040h
- MOV DS,AX
-
- Otro aspecto que querría comentar respecto a la instrucción 'MOV': el
- código de operación de las instrucciones de transferencia entre registros in-
- corpora algunos campos que especifican de qué registro a qué registro se mueve
- el dato. Pero en estas últimas instrucciones, el dato que se quiere cargar en
- el registro va con el propio código de operación. Es decir, el 8086 espera
- encontrar el valor a guardar inmediatamente después de lo que constituye el
- verdadero 'opcode' (o código de operación), que es el que identifica a la ins-
- trucción y no depende del valor a guardar. Por eso, las primeras instrucciones
- (MOV AX,BX; etc...) sólo ocupan dos bytes (ambos forman el código de operación
- de la instrucción), mientras que las otras (MOV AX,1; etc...) ocupan dos o tres
- bytes. ¿A qué se debe esta diferencia del tamaño? Se debe a una característica
- del 8086 de la que todavía no hemos hablado:
-
- Cuando se diseñó el 8086, se penso (hicieron bien) que en algunos casos
- interesaría acceder por separado al byte alto y byte bajo que componen los
- registros, de manera que podamos operar con valores del tamaño de un byte. Por
- tanto, se incluyeron instrucciones que en lugar de operar sobre los registros
- de 16 bits completos operaban sobre los bytes que los componen. Esta subdivi-
- sión sólo se hizo para los cuatro registros de propósito general, y en ASM se
- identifican con los siguientes nombres:
-
- AX -> AH (byte alto) y AL (byte bajo)
- BX -> BH ( " " ) y BL ( " " )
- CX -> CH ( " " ) y CL ( " " )
- DX -> DH ( " " ) y DL ( " " )
-
- Así, las siguientes instrucciones también tienen su correspondiente
- código de operación. Espero que su función resulte obvia:
-
- MOV AL,BL
- MOV CH,CL
- MOV DL,5
- MOV BH,2
-
- Es necesario dejar claro que los registros AL y AH, por ejemplo, son parte
- del propio AX y por tanto no son independientes de éste. Por tanto, tras
- ejecutar las siguientes instrucciones:
-
- MOV AX,0FFFFh
- MOV AL,00
- MOV AH,00
-
- El registro AX valdrá 0000, ya que tanto su byte alto como su byte bajo se
- han puesto a cero.
-
- El tamaño de la instrucción 'MOV reg,valor', volviendo a donde lo dejamos,
- depende del tamaño del registro que se modifique. Si se modifica un registro de
- 16 bits, el dato que viene a continuación debe ser de éste tamaño, por lo que
- además del byte con el opcode necesitamos otros dos con el valor, por lo que el
- total es de tres bytes. En cambio, en una instrucción como 'MOV AL,00' sólo es
- necesario un byte con el valor después del opcode, por lo que el tamaño total
- de la instrucción es de dos bytes.
-
- Otro de los posibles usos de la instrucción MOV es el de cargar un registro
- con el contenido de una posición de memoria. El operando destino indicará el
- registro en el que se debe almacenar el valo, mientras que el operando origen
- será la dirección de la que se debe cargar el dato. Para indicar que lo que se
- quiere cargar es el valor contenido en la posición de memoria dada, se encierra
- la dirección entre corchetes:
-
- MOV AL,[0000] ; Carga el valor de la posición cero en AL,
- ; a diferencia de la siguiente instrucción,
- MOV AH,00 ; que carga el VALOR 0 en AH
-
- Ya que con los 16 bits que damos como dirección de memoria (no se pueden
- dar los 20 bits completos) no se puede generar la dirección completa, se usa
- el registro DS para formarla como vimos en el capítulo anterior. Más adelante
- veremos cómo se puede especificar que se use otro registro.
-
- Esto se denomina 'direccionamiento indirecto', en el que el operando es una
- posición de memoria de la que cargar el dato en lugar del valor a cargar. A
- proposito, el dar directamente el valor se denomina 'direccionamiento
- inmediato'.
-
- Si el registro indicado es de 16 bits, se carga el byte bajo de la dirección
- dada y el byte alto de la siguiente (ordenamiento Intel, ¿recordáis?).
-
- MOV AX,[0000] ; Carga el valor de la posición 0 en AL
- ; y el de la posición 1 en AH
-
- Al igual que se puede cargar un registro con el contenido de una posición
- de memoria, se puede almacenar el contenido de un registro en una posición de
- memoria. La instrucción, como habréis adivinado, queda así:
-
- MOV [0000],AX ; Almacena AL en la pos. 0 y AH en la pos. 1
- MOV [0505h],AL ; Almacena AL en la pos 0505h
-
- Aunque así podemos acceder a posiciones de memoria determinadas, a menudo
- interesa acceder a la posición de memoria indicada por un registro. En el caso
- del 8086, es posible acceder a la posición de memoria apuntada por BX, tanto
- para lectura como para escritura, de esta forma:
-
- MOV AL,[BX] ; Carga en AL el valor almacenado en la
- ; posición de memoria dada por BX
- MOV [BX],DX ; Almacena DL en la posición dada por BX,
- ; y DH en la posición siguiente
-
- Para darnos más posibilidades, los códigos de operación del 8086 incluyen
- un acceso a memoria a una posición nn bytes más adelante de la dada por BX,
- todo en una sola instrucción:
-
- MOV AX,[BX+15d] ; Carga los dos bytes de la posición apuntada
- ; por BX más 15 y de la siguiente
- MOV [BX-12d],DL ; Almacena DL en la dirección dada por BX
- ; menos 12
-
- Este valor que se suma a BX antes de generar el acceso a memoria viene, de
- la misma manera que el valor en el direccionamiento inmediato, inmediatamente
- después del código de operación, y forma parte de la instrucción. Si el valor
- del desplazamiento está entre -128d y +127d, es decir, 'cabe' en un byte
- (ya que el desplazamiento se interpreta como entero con signo), se genera una
- instrucción un byte más corta que si el valor necesita una palabra entera. De
- todas formas, el desplazamiento (el valor que se suma a BX) nunca puede salirse
- de una palabra.
-
- Hemos visto que el acceso a memoria por medio de un registro lo hacemos
- siempre con el BX. De hecho, no existen códigos de operación para acceder con
- el AX, el CX y el DX. Por tanto las siguientes instrucciones no las acceptará
- el ensamblador:
-
- MOV BX,[AX] ; MAL
- MOV CL,[DX] ; MAL
-
- Y ahora, viendo esta limitación de registros para apuntar a memoria, llega
- el momento de introducir otros dos registros: el SI ('Source Index') y el DI
- ('Destination Index'). Estos registros admiten todos los modos de direcciona-
- miento que hemos visto, y además algunos que todavía no conocemos. La única
- diferencia es que no se puede acceder por separado a los bytes alto y bajo, por
- lo que siempre usaremos los registros 'enteros'.
-
- Por ejemplo, podemos hacer cosas como:
-
- MOV AX,0040h
- MOV DS,AX ; Segmento de datos a partir de 00400h absoluta
- MOV SI,2
- MOV AX,[SI] ; Carga el byte almacenado en 00402h absoluta
- ; en AL, y el de 00403h en AH
-
- Bueno, en el siguiente capítulo seguiremos con más usos de la instrucción
- MOV (más modos de direccionamiento) y veremos cómo experimentar con el DEBUG.
- Pensaba explicar todo esto en un sólo capítulo, pero se me alarga demasié.
-
- Salut!!! :-)
-
- Jon